package com.zhny.sprinkler.irrigation.machine.rtu.plugin;

import com.google.common.collect.ImmutableMap;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.model.IRequestMessage;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.modbus.ModemEngine;
import com.zhny.aiot.plugin.modbus.device.ModemConfig;
import com.zhny.aiot.plugin.modbus.device.ModemDevice;
import com.zhny.aiot.plugin.modbus.device.modbus.ModbusCommandParam;
import com.zhny.aiot.plugin.modbus.handler.model.ModemRequestMessage;
import com.zhny.aiot.plugin.modbus.handler.model.ModemResponseMessage;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.model.TaskEntity;
import com.zhny.sprinkler.irrigation.machine.rtu.plugin.model.SprinklerRTUStoreEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class SprinklerRTUDevice extends ModemDevice<SprinklerRTUStoreEntry> {
    private static final Logger logger=LoggerFactory.getLogger (SprinklerRTUDevice.class);
    private final Map<String, ModbusCommandParam> CommandOperations;

    public SprinklerRTUDevice(ModemEngine engine, IDeviceFactory<ModemConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super (engine, factory, centerFacilities, entity);
        CommandOperations=new ImmutableMap.Builder<String, ModbusCommandParam> ()
                .put ("sprinklerQuery", ModbusCommandParam.valueOf ((short) 3, 3, 1))
                .put ("sprinklerOpen", ModbusCommandParam.valueOf ((short) 6, 10, 0x0065))
                .put ("sprinklerClose", ModbusCommandParam.valueOf ((short) 6, 10, 0x0066))
                .put ("sprinklerStop", ModbusCommandParam.valueOf ((short) 6, 10, 0x0068))
                .put ("sprinklerModelClockwise", ModbusCommandParam.valueOf ((short) 6, 11, 0x0065))
                .put ("sprinklerModelAnticlockwise", ModbusCommandParam.valueOf ((short) 6, 11, 0x0066))
                .put ("sprinklerModelQuery", ModbusCommandParam.valueOf ((short) 3, 4, 1))
                .put ("pressureQuery", ModbusCommandParam.valueOf ((short) 4, 5, 1))
                .build ();
    }

    @Override
    public void onDecoder(ModemResponseMessage modemResponseMessage) {
        logger.info ("-------zhny sprinkler rtu decoder start-------");
        MessageEntry entry=MessageUtils.createMessageEntry (this.getId ());
        entry.setType (MessageType.RESULT);
        String address=modemResponseMessage.getKey ();
        SprinklerRTUStoreEntry storeEntry=new SprinklerRTUStoreEntry ();
        int val=modemResponseMessage.getData ().readUnsignedShort ();
        if(modemResponseMessage.getFunction () == 0x06) {
            if(modemResponseMessage.getSize () == 10) {
                String value=
                        val == 0x65 ? "顺时针转动" :
                        val == 0x66 ? "逆时针转动" :
                        val == 0x68 ? "停止" : "未知";
                storeEntry.setSprinklerStatus (value);
            }else if(modemResponseMessage.getSize () == 11) {
                String value=
                        val == 0x65 ? "顺时针转动" :
                        val == 0x66 ? "逆时针转动" : "未选定";
                storeEntry.setSprinklerModel (value);
            }else if(modemResponseMessage.getSize () == 12) {
                storeEntry.setPressure ("压力报警");
                entry.setData (storeEntry);
                entry.setType (MessageType.ALARM);
                nofity (entry);
                return;
            }
        }else if(modemResponseMessage.getFunction () == 0x03) {
            String value=val == 0x80 ? "顺时针转动" :
                    val == 0x81 ? "逆时针转动" : "未选定";
            storeEntry.setSprinklerModel (value);
        }else if(modemResponseMessage.getFunction () == 0x04) {
            double value=val / 2000.0000;
            storeEntry.setPressure (String.valueOf (value));
        }else {
            storeEntry.setSprinklerStatus ("数据错误");
            entry.setData (storeEntry);
            entry.setType (MessageType.ERROR);
            nofity (entry);
            return;
        }

        logger.info ("-------sprinkler rtu：{},值:{}-------", this.getDeviceEntity ().getName (), storeEntry);
        entry.setData (storeEntry);
        nofity (entry);
        saveReal (storeEntry);
        save (storeEntry);
    }

    @Override
    protected IRequestMessage getCommand(TaskEntity taskEntity) {
        logger.info ("-------zhny sprinkler rtu encode command !-------");
        MessageEntry entry=MessageUtils.createMessageEntry (this.getId ());
        entry.getProperties ().put ("task_name", taskEntity.getMethodName ());
        entry.setType (MessageType.OPERATION);
        ModbusCommandParam command=CommandOperations.get (taskEntity.getMethodName ());
        if(command == null) {
            entry.setType (MessageType.ERROR);
            entry.setData (String.format ("factory[%s] no support command [%s]", getTypeId (), taskEntity.getMethodName ()));
            this.nofity (entry);
            return null;
        }
        String methodName=taskEntity.getMethodName ();
        logger.info ("-------zhny sprinkler rtu {},{} command !-------", this.getDeviceEntity ().getName (), methodName);
        logger.info ("-------zhny sprinkler rtu encode a:{}-o:{}-r:{}-d:{}!-------", this.getConfig ().getAddress (), command.getOper (), command.getRegAdress (), command.getDataSize ());
        return new ModemRequestMessage (
                Integer.valueOf (this.getConfig ().getAddress ()),
                command.getOper (),
                command.getRegAdress (),
                command.getDataSize ()
        );
    }

    @Override
    protected void disposable() {

    }
}
